#ifndef CACULATOR_H
#define CACULATOR_H
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<cmath>
using namespace std;

//所有符号
enum All_Char {num,pot,opt,brkt};

//括号类型
enum Bracket {none,lft,rit};


bool IsStringGood(string str);
bool IsOperator(char ch);
int CharPriority(char ch);
void String_MiddletoPost(string infix,string & postfix);
double Calculator_by_Post(string & postfix);

//基本判断表达式是否满足要求
bool IsStringGood(string str)
{
    bool is_string_good = true;
    string::iterator it;


    //1,输入中有其他符号
     for(int i=0;i<str.size();i++)
    {
        if(str[i] !='+' && str[i] !='-'&& str[i] !='*' && str[i] !='/' && 
        str[i] !='^' && str[i] !='.'&& (str[i] < '0' || str[i] > '9')
        && str[i] != '(' && str[i] != ')')
        {
            cerr << " 算式中有其他符号"<<endl;
            return 0;
        }
    }

    //2,开头结尾是运算符或者小数点
   
    char ppt;
    ppt= str[str.length()-1];
    if(ppt=='+'||ppt=='-'||ppt=='*'||ppt=='/'||ppt=='^')
    {
        cerr << "  首尾有错误"<<endl;
        return 0;
    }

    ppt= str[0];
    if(ppt=='+'||ppt=='-'||ppt=='*'||ppt=='/'||ppt=='^')
    {cerr << "  首尾有错误"<<endl;return 0;}


    //3,连续的运算符或小数点或括号（除了‘（（’或‘））’）或'*('或')*'
    All_Char p=num;//得到的char
    Bracket bt = none;//得到的bracket of char
    for(int j=0;j<str.size();j++)
    {
        if(str[j] == '.')
        {
            if( p==pot || p==opt || p==brkt)
            {
                cerr << "  小数点不符合规范"<<endl;
                return 0;
            }
            p = pot;
            bt =none;
        }

        else if(str[j] =='*' || str[j] =='/' || 
        str[j] =='^')
        {
            if( p ==pot || p == opt || bt == lft )
            {cerr << "  运算符不符合规范"<<endl;return 0; }
            p = opt;
            bt =none;
        }

        else if(str[j] =='+' || str[j] =='-' )
        {
            if( p ==pot || p == opt )
            {cerr << "  运算符不符合规范"<<endl;return 0; }
            p = opt;
            bt =none;
        }

        else if(str[j] == '(')
        {
            if( p ==pot  )
            {cerr << "  括号不符合规范"<<endl;return 0;}
            if( bt == rit)
            {cerr << "  括号不符合规范"<<endl;return 0;}
            p = brkt;
            bt=lft;
        }

        else if(str[j] == ')')
        {
            if( p ==pot || p == opt)
            {cerr << "  括号不符合规范"<<endl;return 0;}
            if( bt == lft)
            {cerr << "  括号不符合规范"<<endl;return 0;}
            p = brkt;
            bt=rit;
        }
        else {p=num,bt =none;}
    }


    //4,aa.bbb.c+aa.c.d问题
    stack <int> stack_pot;
    while (!stack_pot.empty ()) {stack_pot.pop ();}
    int count=0;

    //记录所有小数点
    for (int q=0;q<str.size();q++)
    {
        if(str[q]=='.')
            {
                stack_pot.push(q);    
            }
    }

    //是否两个小数点之间都是数字
    while(stack_pot.size()>=2)
    {
        count =0;
        int x1=stack_pot.top();
        stack_pot.pop();
        int x2=stack_pot.top();

        for(int e=x2;e<=x1;e++)
        {
            if(str[e]>='0'&&str[e]<='9')
            {count++;}
        }
        if(count == x1-x2-1) 
        {
            cerr<<"  您的浮点数输入有误"<<endl;
            return 0;
        }
        
    }


    //5,括号不匹配
    stack <char> stack_brkt;
    while (!stack_brkt.empty ())
    {stack_brkt.pop();}

    for (int k =0;k<str.size();k++) 
    {
        if (str[k] == '(' )
            stack_brkt.push (str[k]);
        else 
        {
            if (str[k] == ')')
            {
                if (stack_brkt.empty () 
                || stack_brkt.top () != '(')
                    {
                        cerr << "  括号不匹配"<<endl;
                        return 0;
                    }

                else {stack_brkt.pop ();}
            }
        }
    }

    if (!stack_brkt.empty ())
        {
            cerr<<"  括号不匹配"<<endl;
            return 0;
        }
    return 1;
}

//判断是否是运算符
bool IsOperator(char ch)
{
	switch(ch)
	{
	case '+':
	case '-':
	case '*':
	case '/':
    case '^':
		return true;
	default:
		return false;
	}
}

//判断运算符优先级
int CharPriority(char ch)
{
	switch(ch)
	{
	case '(':
		return 0;
	case '+':
	case '-':
		return 1;
	case '*':
	case '/':
		return 2;
    case '^':
        return 3;

	default:
		return -1;
	}
}

//表达式中缀转后缀
void String_MiddletoPost(string infix,string & postfix)
{
    //6,(+3-12)或者(-1)^(3)等问题
    if(infix.find('(')!=-1)
    {
        int g=0;
        while(infix[g]!='\0')
        {
            if(infix.substr(g,infix.size()).find('(')==-1) break;
            if(infix[g]=='(')
            {
                if(infix[++g]=='+'||infix[g]=='-')
                {
                    infix.insert(g,"0");
                }
            }
		++g;
	    }
    }
    

    //栈用来放运算符和括号
	stack<char> stack_opt;
    postfix.clear();
    //表示结束
    stack_opt.push('@');
	int i;
    int j=0;
    

	for( i=0;i<infix.size();i++)
	{
        //碰到数字一直放入postfix
		if((infix[i]>='0'&&infix[i]<='9')||infix[i]=='.')
		{
			postfix.push_back(infix[i]);
		}

        //'('入栈
		else if(infix[i]=='(')
		{
			stack_opt.push(infix[i]);
		}

        //碰到')'时弹出栈内在'('前的运算符
		else if(infix[i]==')')
		{
			while(stack_opt.top()!='(')
			{
				postfix.push_back(' ');
				postfix.push_back(stack_opt.top());
				stack_opt.pop();
			}

            //以防额外括号不对的情况
            if(stack_opt.top()!='(')
            {
                cerr<<"  括号不匹配" <<endl;
            }
			stack_opt.pop();
		}

        //碰到运算符比较优先级
		else if(IsOperator(infix[i]))
		{
            //因为有小数点存在，用空格隔开数字和运算符
			postfix.push_back(' ');
			if(stack_opt.empty())
			{
				stack_opt.push(infix[i]);
			}

			else
			{
                //栈中运算符优先级高的化弹出
				while(CharPriority(infix[i])<=CharPriority(stack_opt.top()))
				{
					postfix.push_back(stack_opt.top());
					postfix.push_back(' ');
					stack_opt.pop();
				}
				stack_opt.push(infix[i]);
			}
		}
	}

	while(stack_opt.size())
	{  
        postfix.push_back(' ');
        postfix.push_back(stack_opt.top());
        stack_opt.pop();
	}
    postfix.pop_back();

    
}


//表达式求值
double Calculator_by_Post(string & postfix)
{
	stack<double> stack_digit;
	int i=0;
	double digit1=0,digit2=0;
    //计算结果
    double result = -1;
    //运算是否成功
    bool ff=1;

	while(postfix[i]!='\0')
	{
        //处理数字
		if(postfix[i]>='0' && postfix[i]<='9')
		{
			double digit=0;
			while(postfix[i]>='0' && postfix[i]<='9')
			{
				digit=digit*10+(postfix[i]-'0');
				i++;
			}
			//处理小数点
            int n=0;//小数点后位数
			if(postfix[i]=='.')
			{
				i++;
				while(postfix[i]>='0' && postfix[i]<='9')
				{
					digit=digit*10+(postfix[i]-'0');
					i++;
					n++;
				}
			}
            //挪小数点
			while(n)
			{
				digit/=10;
				n--;
			}
			stack_digit.push(digit);
		}


        //空格跳过
		else if(postfix[i]==' ')
		{
			i++;
		}


		else if(postfix[i]=='+')
		{
			digit1=stack_digit.top();
			stack_digit.pop();
			digit2=stack_digit.top();
			stack_digit.pop();
			double temp=digit2+digit1;
			stack_digit.push(temp);
			i++;
		}
		else if(postfix[i]=='-')
		{
			digit1=stack_digit.top();
			stack_digit.pop();
			digit2=stack_digit.top();
			stack_digit.pop();
			double temp=digit2-digit1;
			stack_digit.push(temp);
			i++;
		}
		else if(postfix[i]=='*')
		{
			digit1=stack_digit.top();
			stack_digit.pop();
			digit2=stack_digit.top();
			stack_digit.pop();
			double temp=digit2*digit1;
			stack_digit.push(temp);
			i++;
		}
		else if(postfix[i]=='/')
		{
            if(stack_digit.top()==0)
            {
                cerr<<"  除数为0,无意义"<<endl;
                ff=0;
                i++;
            }

            else
            {
                digit1=stack_digit.top();
                stack_digit.pop();
                digit2=stack_digit.top();
                stack_digit.pop();
                double temp=digit2/digit1;
                stack_digit.push(temp);
                i++;
            }
		}
        else if(postfix[i]=='^')
		{
			digit1=stack_digit.top();
			stack_digit.pop();
			digit2=stack_digit.top();
			stack_digit.pop();
            // if(( ((int)digit1)/10*10)!=digit1  && digit2<=0)
            // {
            //     cerr<<"  负数的非整数幂次,错误"<<endl;
            //     ff=0;
            // }
        
            double temp=pow(digit2,digit1);
            stack_digit.push(temp);
            i++;
		}
	}

	result=stack_digit.top();
    stack_digit.pop();

    if(!stack_digit.empty())
    {cerr<<"  您输入的表达式有误"<<endl;}

    if(!ff)
    {cerr<<"  请重新输入正确表达式,下方计算结果无效"<<endl;}
    return result;
}








#endif